package org.sjs.dreamfly.player

import android.annotation.SuppressLint
import android.app.Activity
import android.content.pm.ActivityInfo
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import kotlinx.coroutines.launch
import org.sjs.dreamfly.R
import org.sjs.dreamfly.common.util.LogUtil
import org.sjs.dreamfly.common.util.Router
import org.sjs.dreamfly.common.util.PhemonUtils
import org.sjs.dreamfly.common.util.PlayUtil
import org.sjs.dreamfly.model.VideoInfo
import org.sjs.dreamfly.widget.PlayerView
import org.sjs.dreamfly.widget.TitleBar
import java.lang.ref.WeakReference


class ShortVideoPlayerFragment : PlayerFragment() {

    private lateinit var viewPager: ViewPager2

    override fun requireLayoutId(): Int {
        return R.layout.fragment_player2
    }

    override fun onPause() {
        super.onPause()
        VH.pauseAll()
    }

    override fun onDestroy() {
        super.onDestroy()
        VH.releaseAll()
    }

    override fun onBindViews() {
        viewPager = requireView().findViewById(R.id.view_pager)
    }

    override fun onInitViews() {
        initViewPager()
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onLoadData() {
        mainScope.launch {
            viewModel?.loadVideoList()?.let {
                LogUtil.d("size: " + it.size)
            }
            viewPager.adapter?.notifyDataSetChanged()
        }
    }

    override fun saveHistory(): Boolean {
        PhemonUtils.TODO("保存历史记录未实现")
        return false
    }

    private fun initViewPager() {
        viewPager.orientation = ViewPager2.ORIENTATION_VERTICAL
        viewPager.adapter = object : RecyclerView.Adapter<VH>() {
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
                val inflate: View = LayoutInflater.from(parent.context)
                    .inflate(R.layout.view_holder_short_video_page, null)
                val layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT)

                inflate.layoutParams = layoutParams
                return VH(inflate)
            }
            override fun onBindViewHolder(holder: VH, position: Int) {
                viewModel?.getVideoList()?.get(position)?.let {
                    holder.bind(it, position)
                }
            }
            override fun getItemCount(): Int {
                return viewModel?.getVideoList()?.size?:0
            }
            override fun onViewRecycled(holder: VH) {
                holder.recycle()
            }
        }
        arguments?.getInt(Router.KEY_INDEX)?.let {
            if (it > 0 && it < viewPager.adapter!!.itemCount) {
                viewPager.currentItem = it
            }
        }
        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            @SuppressLint("NotifyDataSetChanged")
            override fun onPageSelected(position: Int) {
                (viewPager.getChildAt(0) as RecyclerView).findViewHolderForAdapterPosition(position)?.let {
                    viewModel?.getVideoList()?.get(position)?.let { videoInfo->
                        (it as VH).play(videoInfo)
                        LogUtil.d("play:$videoInfo")
                    }
                }

                if (viewModel != null && position == viewModel!!.getVideoList().size - 2) {
                    viewModel?.loadMore {
                        viewPager.adapter?.notifyDataSetChanged()
                    }
                }
            }
        })
    }

    class VH(itemView: View) : RecyclerView.ViewHolder(itemView), IPlayerDataProvider,
        PlayerView.ActionListener {
        companion object {
            val playerList = mutableListOf<WeakReference<ExoPlayer>>()

            fun pauseOthers(player: ExoPlayer) {
                playerList.removeAll { it.get() == null }
                playerList.forEach {
                    it.get()?.let { item ->
                        if ( item != player) {
                            item.playWhenReady = false
                            item.pause()
                        }
                    }
                }
            }

            fun pauseAll() {
                playerList.removeAll { it.get() == null }
                playerList.forEach {
                    it.get()?.let { item ->
                        item.playWhenReady = false
                        item.pause()
                    }
                }
            }

            fun releaseAll() {
                playerList.forEach {
                    it.get()?.release()
                }
                playerList.clear()
            }
        }

        private var exoPlayer: ExoPlayer? = null
        private var currentPos = -1
        private var videoView: PlayerView
        private var coverView: ImageView
        private var bindVideoInfo: VideoInfo? = null

        init {
            videoView = itemView.findViewById(R.id.video_view)
            coverView = itemView.findViewById<ImageView>(R.id.video_cover)
            videoView.setControllerOnFullScreenModeChangedListener {
                if ((itemView.context as Activity).requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                    (itemView.context as Activity).requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
                } else {
                    (itemView.context as Activity).requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                }
            }
            videoView.controllerAutoShow = false
            videoView.addListener(this)
            videoView.setDataProvider(this)
        }

        override fun getVideoList(): MutableList<VideoInfo> {
            bindVideoInfo?.let { return mutableListOf(it) }?:return mutableListOf()
        }

        override fun onBackButtonClick() {
            if ((itemView.context as? Activity)?.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                (itemView.context as Activity).requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            } else {
                (itemView.context as Activity).finish()
            }
        }

        private fun makePlayerExist() {
            if (exoPlayer == null) {
                exoPlayer = ExoPlayer.Builder(itemView.context).build().apply {
                    // FIXME: 只有add没有remove潜在风险
                    addListener(object : Player.Listener {
                        override fun onPlaybackStateChanged(playbackState: Int) {
                            LogUtil.d("[$currentPos] - $playbackState player:${this@apply.hashCode()}")
                        }

                        override fun onRenderedFirstFrame() {
                            coverView.visibility = View.GONE
                        }
                    })
                    playerList.add(WeakReference(this))
                    LogUtil.d("VH:${this@VH.hashCode()} player:${this.hashCode()}")
                }
            }
        }

        fun play(videoInfo: VideoInfo) {
            exoPlayer?.let {
                pauseOthers(it)
                it.playWhenReady = true
                if (it.mediaItemCount == 0 ) {
                    PlayUtil.playVideo(itemView.context, videoView, videoInfo.videoUrl?:"", exoPlayer)
                }
                it.play()
                videoView.hideController()
            }
        }

        fun bind(videoInfo: VideoInfo, position: Int) {
            bindVideoInfo = videoInfo
            makePlayerExist()
            LogUtil.d("[$position]-VH:${hashCode()} player:${exoPlayer.hashCode()}")
            currentPos = position
            videoView.updateTitle()
            Glide.with(itemView).load(videoInfo.imageUrl).into(coverView)
            PlayUtil.playVideo(itemView.context, videoView, videoInfo.videoUrl?:"", exoPlayer)
        }

        /**
         * 对象还会被捞回来复用
         */
        fun recycle() {
            LogUtil.d("lastBindPos-[$currentPos] VH:${hashCode()} player:${exoPlayer.hashCode()}")
            exoPlayer?.release()
            exoPlayer = null
        }
    }
}


